<template>
    <div class="roles">
        <!-- 面包屑导航 -->
        <el-row>
            <el-col>
                <el-breadcrumb separator-class="el-icon-arrow-right">
                    <el-breadcrumb-item :to="{ path: '/welcome' }">{{
                        $t('rights.home')
                    }}</el-breadcrumb-item>
                    <el-breadcrumb-item>{{
                        $t('rights.RightsManage')
                    }}</el-breadcrumb-item>
                    <el-breadcrumb-item>{{
                        $t('rights.RoleList')
                    }}</el-breadcrumb-item>
                </el-breadcrumb>
            </el-col>
        </el-row>

        <!-- 添加角色按钮 -->
        <el-row>
            <el-col>
                <el-button
                    class="rolesBtn"
                    type="primary"
                    v-on:click="adddialogFormVisible = true"
                    >{{ $t('rights.add') }}</el-button
                >
            </el-col>
        </el-row>

        <!-- 角色列表 -->
        <el-row class="rolesList">
            <el-col>
                <el-table :data="roleList" border style="width: 100%">
                    <el-table-column
                        type="expand"
                        :label="$t('rights.rights')"
                        width="70"
                        align="center"
                    >
                        <template slot-scope="scope">
                            <el-row
                                class="flexCenter"
                                v-bind:class="{
                                    borderTop: index1 === 0,
                                    borderBottom: true,
                                }"
                                v-for="(item1, index1) in scope.row.children"
                                v-bind:key="index1"
                            >
                                <!-- 渲染一级权限 -->
                                <el-col v-bind:span="4">
                                    <el-tag
                                        closable
                                        v-on:close="
                                            removeRightById(scope.row, item1.id)
                                        "
                                        >{{ item1.authName }}</el-tag
                                    >
                                    <i class="el-icon-caret-right"></i>
                                </el-col>
                                <!-- 用来渲染二级权限和三级权限 -->
                                <el-col v-bind:span="20">
                                    <!-- 循环遍历 item  -->
                                    <el-row
                                        class="flexCenter"
                                        v-bind:class="{
                                            borderTop: index2 !== 0,
                                        }"
                                        v-for="(
                                            item2, index2
                                        ) in item1.children"
                                        v-bind:key="index2"
                                    >
                                        <!-- 二级权限 -->
                                        <el-col v-bind:span="6">
                                            <el-tag
                                                type="success"
                                                closable
                                                v-on:close="
                                                    removeRightById(
                                                        scope.row,
                                                        item2.id
                                                    )
                                                "
                                                >{{ item2.authName }}</el-tag
                                            >
                                            <i class="el-icon-caret-right"></i>
                                        </el-col>
                                        <!-- 三级权限 -->
                                        <el-col v-bind:span="18">
                                            <el-tag
                                                type="warning"
                                                v-for="(
                                                    item3, index3
                                                ) in item2.children"
                                                v-bind:key="index3"
                                                closable
                                                v-on:close="
                                                    removeRightById(
                                                        scope.row,
                                                        item3.id
                                                    )
                                                "
                                                >{{ item3.authName }}</el-tag
                                            >
                                        </el-col>
                                    </el-row>
                                </el-col>
                            </el-row>
                        </template>
                    </el-table-column>
                    <el-table-column
                        type="index"
                        :label="$t('rights.id')"
                        width="60"
                        align="center"
                    >
                    </el-table-column>
                    <el-table-column
                        prop="roleName"
                        :label="$t('rights.roleName')"
                    >
                    </el-table-column>
                    <el-table-column
                        prop="roleDesc"
                        :label="$t('rights.roleDesc')"
                    >
                    </el-table-column>
                    <el-table-column :label="$t('rights.operate')">
                        <template slot-scope="scope">
                            <el-tooltip
                                class="item"
                                effect="dark"
                                :content="$t('rights.editRole')"
                                placement="top-end"
                            >
                                <el-button
                                    size="mini"
                                    type="primary"
                                    icon="el-icon-edit"
                                    circle
                                    v-on:click="editeQuery(scope.row.id)"
                                ></el-button>
                            </el-tooltip>

                            <el-tooltip
                                class="item"
                                effect="dark"
                                :content="$t('rights.delRole')"
                                placement="top-end"
                            >
                                <el-button
                                    size="mini"
                                    type="danger"
                                    icon="el-icon-delete"
                                    circle
                                    v-on:click="handleDel(scope.row.id)"
                                ></el-button>
                            </el-tooltip>

                            <el-tooltip
                                class="item"
                                effect="dark"
                                :content="$t('rights.distributeRights')"
                                placement="top-end"
                            >
                                <el-button
                                    size="mini"
                                    type="info"
                                    icon="el-icon-setting"
                                    circle
                                    v-on:click="ShowRightDialog(scope.row)"
                                ></el-button>
                            </el-tooltip>
                        </template>
                    </el-table-column>
                </el-table>
            </el-col>
        </el-row>

        <!-- 添加角色对话框 -->
        <el-dialog
            :title="$t('rights.add')"
            :visible.sync="adddialogFormVisible"
            center
            v-on:close="Close"
        >
            <el-form :model="roleForm" v-bind:rules="Rules" ref="form">
                <el-form-item
                    :label="$t('rights.roleName')"
                    :label-width="formLabelWidth"
                    prop="roleName"
                >
                    <el-input
                        v-model="roleForm.roleName"
                        autocomplete="off"
                    ></el-input>
                </el-form-item>

                <el-form-item
                    :label="$t('rights.roleDesc')"
                    :label-width="formLabelWidth"
                    prop="roleDesc"
                >
                    <el-input
                        v-model="roleForm.roleDesc"
                        autocomplete="off"
                    ></el-input>
                </el-form-item>
            </el-form>

            <div slot="footer" class="dialog-footer">
                <el-button @click="resetForm">{{
                    $t('rights.reset')
                }}</el-button>
                <el-button type="primary" @click="handleAdd">{{
                    $t('rights.define')
                }}</el-button>
            </div>
        </el-dialog>

        <!-- 编辑角色对话框 -->
        <el-dialog
            :title="$t('rights.editRole')"
            :visible.sync="editedialogFormVisible"
            center
            v-on:close="Close"
        >
            <el-form :model="editeForm" v-bind:rules="Rules" ref="form">
                <el-form-item
                    :label="$t('rights.roleName')"
                    :label-width="formLabelWidth"
                    prop="roleName"
                >
                    <el-input
                        v-model="editeForm.roleName"
                        autocomplete="off"
                    ></el-input>
                </el-form-item>

                <el-form-item
                    :label="$t('rights.roleDesc')"
                    :label-width="formLabelWidth"
                    prop="roleDesc"
                >
                    <el-input
                        v-model="editeForm.roleDesc"
                        autocomplete="off"
                    ></el-input>
                </el-form-item>
            </el-form>

            <div slot="footer" class="dialog-footer">
                <el-button @click="resetForm">{{
                    $t('rights.reset')
                }}</el-button>
                <el-button type="primary" @click="handleEdite">{{
                    $t('rights.define')
                }}</el-button>
            </div>
        </el-dialog>

        <!-- 分配权限对话框 -->
        <el-dialog
            :title="$t('rights.distributeRights')"
            :visible.sync="setRightdialogFormVisible"
            center
            width="40%"
            v-on:close="setRightDialogClose"
        >
            <!-- 树形组件 -->
            <el-tree
                :data="rightsList"
                :props="treeProps"
                show-checkbox
                node-key="id"
                default-expand-all
                v-bind:default-checked-keys="defKeys"
                ref="treeRef"
            ></el-tree>

            <div slot="footer" class="dialog-footer">
                <el-button @click="setRightdialogFormVisible = false">{{
                    $t('rights.cancel')
                }}</el-button>
                <el-button type="primary" @click="allotRights">{{
                    $t('rights.define')
                }}</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
export default {
    name: 'rolesWrap',
    data() {
        return {
            // 角色列表
            roleList: [],
            // 控制添加角色对话框是否展示
            adddialogFormVisible: false,
            // 控制编辑角色对话框是否展示
            editedialogFormVisible: false,
            // 控制分配权限对话框是否展示
            setRightdialogFormVisible: false,
            // 添加角色的字段信息
            roleForm: {
                // 角色名称
                roleName: '',
                // 角色描述
                roleDesc: '',
            },
            // 编辑角色的字段信息
            editeForm: {
                // 角色名称
                roleName: '',
                // 角色描述
                roleDesc: '',
            },
            // 表单宽度
            formLabelWidth: '120px',
            // 所有权限的数据
            rightsList: [],
            // 树形组件的绑定对象
            treeProps: {
                children: 'children',
                label: 'authName',
            },
            // 默认选中的节点id值数组
            defKeys: [],
            // 当前即将分配权限的角色id
            roleId: '',
            // 角色的验证规则
            Rules: {
                roleName: [
                    {
                        required: true,
                        message: '角色名称不能为空',
                        trigeer: 'blur',
                    },
                    {
                        min: 2,
                        max: 12,
                        message: '角色名称长度为2-12位',
                        trigeer: 'blur',
                    },
                ],
                roleDesc: [
                    {
                        required: true,
                        message: '角色描述不能为空',
                        trigeer: 'blur',
                    },
                    {
                        min: 3,
                        max: 12,
                        message: '角色描述长度为3-12位',
                        trigeer: 'blur',
                    },
                ],
            },
        }
    },
    methods: {
        // 获取角色列表
        async getRolesList() {
            const res = await this.$http.get('/roles')
            this.roleList = res.data.data
        },
        // 添加角色对话框重置事件
        resetForm() {
            // 将所有表单值重置为初始值并移除校验效果
            this.$refs.form.resetFields()
            this.editeForm.roleName = ''
            this.editeForm.roleDesc = ''
        },
        // 监听对话框关闭时重置事件
        Close() {
            // 将所有表单值重置为初始值并移除校验效果
            this.$refs.form.resetFields()
        },
        // 添加角色对话框保存事件
        async handleAdd() {
            try {
                // 对整个表单进行校验
                await this.$refs.form.validate()
                // 发送添加角色请求
                const res = await this.$http.post('/roles', this.roleForm, {
                    headers: {
                        Authorization: localStorage.getItem('token'),
                    },
                })
                // 获取 msg 和 status
                const {
                    meta: { msg, status },
                } = res.data

                // 如果添加成功
                if (status === 201) {
                    // 提示消息
                    this.$message({
                        type: 'success',
                        message: msg,
                    })
                    // 获取角色列表
                    this.getRolesList()
                    // 关闭添加角色对话框
                    this.adddialogFormVisible = false
                    return
                }
                // 如果失败
                this.$message({
                    type: 'warning',
                    message: msg,
                })
            } catch (err) {
                console.log(err)
            }
        },
        // 根据 ID 查询角色信息
        async editeQuery(id) {
            const res = await this.$http.get(`/roles/${id}`)
            // 获取 msg 和 status
            const {
                meta: { msg, status },
            } = res.data
            // 如果获取成功
            if (status === 200) {
                const { data } = res.data
                // 赋值给编辑角色的字段信息
                this.editeForm = data
                // 展示编辑角色对话框
                this.editedialogFormVisible = true
                return
            }
            // 如果失败
            this.$message({
                type: 'warning',
                message: msg,
            })
        },
        // 编辑角色对话框保存事件
        async handleEdite() {
            try {
                // 对整个表单进行校验
                await this.$refs.form.validate()
                // 发送编辑提交请求
                const res = await this.$http.put(
                    `/roles/${this.editeForm.roleId}`,
                    this.editeForm,
                    {
                        headers: {
                            Authorization: localStorage.getItem('token'),
                        },
                    }
                )
                // 获取 msg 和 status
                const {
                    meta: { msg, status },
                } = res.data
                // 如果获取成功
                if (status === 200) {
                    // 提示消息
                    this.$message({
                        type: 'success',
                        message: '修改成功',
                    })
                    // 获取角色列表
                    this.getRolesList()
                    // 关闭编辑角色对话框
                    this.editedialogFormVisible = false
                    return
                }
                // 如果失败
                this.$message({
                    type: 'warning',
                    message: msg,
                })
            } catch (err) {
                console.log(err)
            }
        },
        // 删除角色
        async handleDel(id) {
            try {
                // 弹框提示
                const result = await this.$confirm(
                    '此操作将永久删除该角色, 是否继续',
                    '提示',
                    {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning',
                    }
                )
                /*
                    - 如果用户点击确定，result 为 confirm
                    - 如果用户点击取消，result 为 cancel
                */
                if (result === 'confirm') {
                    //    请求删除角色接口
                    const res = await this.$http.delete(`/roles/${id}`, {
                        headers: {
                            Authorization: localStorage.getItem('token'),
                        },
                    })
                    // 获取 msg 和 status
                    const {
                        meta: { msg, status },
                    } = res.data
                    // 如果删除成功
                    if (status === 200) {
                        // 提示消息
                        this.$message({
                            type: 'success',
                            message: msg,
                        })
                        // 获取用户列表
                        this.getRolesList()
                        return
                    }
                    // 删除失败时
                    this.$message({
                        type: 'error',
                        message: msg,
                    })
                }
            } catch (err) {
                console.log(err)
                if (err === 'cancel') {
                    // 取消删除时
                    this.$message({
                        type: 'info',
                        message: '已取消删除',
                    })
                }
            }
        },
        // 根据id删除对应的权限
        async removeRightById(role, rightId) {
            try {
                // 弹框提示
                const result = await this.$confirm(
                    '此操作将删除该权限, 是否继续',
                    '提示',
                    {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning',
                    }
                )

                // 如果点击了确定
                if (result === 'confirm') {
                    // 请求删除角色指定权限接口
                    const { data: res } = await this.$http.delete(
                        `/roles/${parseInt(role.id)}/rights/${rightId}`,
                        {
                            headers: {
                                Authorization: localStorage.getItem('token'),
                            },
                        }
                    )
                    console.log(res)
                    // 获取 msg 和 status
                    const {
                        meta: { msg, status },
                    } = res
                    // 如果删除成功
                    if (status === 200) {
                        // 消息提示
                        this.$message.success(msg)
                        // 将最新的权限列表赋值给当前角色的权限列表
                        role.children = res.data
                        return
                    }
                    // 如果失败，消息提示
                    this.$message.error(msg)
                }
            } catch (err) {
                console.log(err)
                if (err === 'cancel') {
                    // 消息提示
                    this.$message.info('已取消了删除')
                }
            }
        },
        // 展示分配权限对话框
        async ShowRightDialog(role) {
            this.roleId = role.id
            // 获取所有权限的数据
            const { data: res } = await this.$http.get('/rights/tree')
            // 获取 msg 和 status
            const {
                meta: { msg, status },
            } = res
            // 如果获取失败
            if (status !== 200) {
                // 消息提示
                return this.$message.error(msg)
            }
            // 把获取到的权限数据赋值给 data 中的权限列表属性
            this.rightsList = res.data
            // 递归获取三级权限的id
            this.getDefKeys(role, this.defKeys)
            // 显示分配权限对话框
            this.setRightdialogFormVisible = true
        },
        // 通过递归的形式，获取角色下所有三级权限的id，并保存到 defKeys 数组中
        getDefKeys(node, arr) {
            // 如果 node 中不包含 children 属性，那么就是三级权限
            if (!node.children) {
                return arr.push(node.id)
            }

            node.children.forEach((item) => this.getDefKeys(item, arr))
        },
        // 监听分配权限的对话框关闭事件
        setRightDialogClose() {
            // 清空用来保存三级权限的id值数组
            this.defKeys = []
        },
        // 点击为角色分配权限
        async allotRights() {
            // 选中的权限id
            const keys = [
                ...this.$refs.treeRef.getCheckedKeys(),
                ...this.$refs.treeRef.getHalfCheckedKeys(),
            ]
            // 将权限id用,拼接成字符串
            const idStr = keys.join(',')
            // 发送角色权限授权接口
            const { data: res } = await this.$http.post(
                `/roles/${this.roleId}/rights`,
                { rids: idStr }
            )
            // 获取 msg 和 status
            const {
                meta: { msg, status },
            } = res
            // 如果设置失败
            if (status !== 200) {
                return this.$message.error(msg)
            }
            // 设置成功时
            this.$message.success(msg)
            // 获取角色列表
            this.getRolesList()
            // 隐藏分配权限对话框
            this.setRightdialogFormVisible = false
        },
    },
    created() {
        // 获取角色列表
        this.getRolesList()
    },
}
</script>

<style lang="less" scoped>
.rolesBtn {
    margin-top: 20px;
}

.rolesList {
    padding: 20px;
    border-radius: 6px;
    box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
    background-color: #fff;
    margin-top: 20px;
    .el-row {
        margin: 0px 30px;
    }
    .el-tag {
        margin: 10px;
    }
    .borderTop {
        border-top: 1px solid #ccc;
    }
    .borderBottom {
        border-bottom: 1px solid #ccc;
    }
}

.flexCenter {
    display: flex;
    align-items: center;
}
</style>
